#ifndef _READ_VIDEO_THREAD_H_
#define _READ_VIDEO_THREAD_H_

#include <iostream>
using namespace std;

#include <string.h>

#include <sys/time.h>
#include <unistd.h>
#include <sys/select.h>

#include <colores.h>
#include "cv.h"
#include "cxcore.h"
#include "highgui.h"
#include "frame_header.hh"

#include "other_functions.h"
#include "Producer.hpp"


/** 
 * \brief Class that contains a single stereo frame information
 * 
 * This class is used to pass the video stereo image frames from the reader to the main program.
 * It provides the two image frames (left and right), and the headers with the information of the frame
 * 
 */
class Cstereo_IplImage {
 public:
    /// Two IplImage pointers to the left and right frames, output size
    IplImage * img[2];
    ///  Two IplImage pointers to the left and right frames, original size in the video
    IplImage * img_ori[2];
    /// The two headers of each image in \c img
    frame_header *head[2];
    
    ///extra information for debugging
    int n;
    /// needed for the function \circular_buffer::print(T*, T*), which requires that the template class implements a function called get1() to retrieve some information of the content
    int get1() {return n;}
    /// needed for the function \circular_buffer::print(T*, T*), which requires that the template class implements a function called get2() to retrieve some information of the content
    int get2() {return head[0]->nframe;}
    /// prints some information from the content of the object
    void print (const char *buf= "")
    {
	printf("%d/%d", n, head[0]->nframe);
    }
};


///type used in the \c class CRead_Video_Thread for the templates
typedef Cstereo_IplImage T;

/** 
 * \brief This class implements the video reader with thread based producer (reader from disk) and 
 * a circular_buffer to communicate read frames to the main thread.
 * 
 */
class CRead_Video_Thread : public CProducer<Cstereo_IplImage> {
 private:
enum video_formats {no_format=0, raw_video, ra2_video, avi_video, format_error};
enum read_video_errors {READVIDEO_ERROR_FILENAME_NOTFOUND, READVIDEO_ERROR_FILENAME_ERROR, 
			READVIDEO_ERROR_FORMAT_ERROR, READVIDEO_ERROR_FORMAT_NOTSUPPORTED};

    enum video_formats video_format;
    int iniframe;
    std::string video_name[2];
    CvSize video_size[2];
    off_t readImageSize[2];
    CvSize video_size_out;
    int offsetx[2];
    int offsety[2];
    FILE* rawvideo[2];
    int video_channels;
    struct timeval oldfilltime[2];
    /// indicates if the output image size is the same than the video frame size
    bool img_not_equal_img_ori[2];
    /// ROI to img IplImages to copy from img_ori in case are not the same size
    CvRect roi[2];
    /// ROI to img_ori IplImages to copy into img in case are not the same size
    CvRect roi_out[2];
    ///Copy of the images for manipulation
    IplImage * img_clone[2];
    IplImage * img_color[2];
    int m_numcams;

 public:
    CRead_Video_Thread (int capacity);
    ~CRead_Video_Thread();

    bool start() ;  
    bool producer_callback(Cstereo_IplImage* pbuf);
    void stop();
    Cstereo_IplImage* consumer();
    int init_params(const char *name, const char * format, int iniframe);
    //void operator()();

    IplImage * img(int n);
    IplImage ** img();
    frame_header * head(int n);
    std::string get_pathbasename(int n=0);
    std::string get_path(int n=0);
    std::string get_filename(int n=0);
    void set_image_size(CvSize size, int x1=-1, int y1=-1, int x2=-1, int y2=-1);
    void set_image_size(int width, int height, int x1=-1, int y1=-1, int x2=-1, int y2=-1);
    IplImage ** cloneimages(int n=-1);
    IplImage * get_cloneimage(int n);
    IplImage ** cloneimages_color(int n=-1);
    IplImage * get_colorimage(int n);
    CvSize image_size();
    int numcams();
    CvRect get_ROI(int i=0);
  
};


#endif //_READ_VIDEO_THREAD_H_


